#include "TPlaca.h"

int Placa_Crear(TPlaca* placa, TDireccion dir) {
	if (PLACA_DEBUG) printf ("Placa_Crear: dir = %d\n", dir);

    if ((dir > DIR_MIN) && (dir < DIR_MAX)) {
        if (PLACA_DEBUG) printf("Placa_Crear: entro al if\n");
        placa->direccion = dir;
        placa->buffer_lleno = 0;

        if (PLACA_DEBUG) printf("Placa_Crear: placa->direccion = %d\n", placa->direccion);

		return PLACA_OK;
	}
    else {
        return PLACA_ERR_RANGO;
	}
}

int Placa_Destruir(TPlaca* placa){
    if (placa->buffer_lleno)
	    free(placa->mensaje);

	return PLACA_OK;
}
TDireccion Placa_GetDireccion(TPlaca* placa) {
	if (PLACA_DEBUG) printf("Placa_GetDireccion:\n placa = %d\n placa->direccion = %x\n", placa, placa->direccion);

	return placa->direccion;
}

int Placa_Recibir(TPlaca* placa, void* mensaje, size_t tam) {
	TDireccion destino;
	char* texto;
	texto = malloc(tam + 1);
	if (PLACA_DEBUG) printf("Placa_Recibir: mensaje = %s\n", (char*)mensaje);

	Mensaje_ObtenerTexto(mensaje, &texto);

	if (strlen(texto) > MTU) {
		free(texto);
		return PLACA_ERR_OVERFLOW;
	}

	Mensaje_ObtenerDireccion(mensaje, &destino);

	if (PLACA_DEBUG) {
		printf("Placa_Recibir:\n destino = %d\n texto = %s\n", destino, texto);
		printf("Placa_Recibir: (destino == placa->direccion)? %d\n", (destino == placa->direccion));
		printf("Placa_Recibir: (destino == DIR_BROADCAST)? %d\n", (destino == DIR_BROADCAST));
	}

	if ((destino == placa->direccion) || (destino == DIR_BROADCAST)) {
		if (PLACA_DEBUG) printf("Placa_Recibir: entra al if\n");
		if (!(placa->buffer_lleno)){
            placa->mensaje = malloc(tam);
            strcpy(placa->mensaje, texto);
            placa->buffer_lleno = 1;
            free(texto);
            return PLACA_OK;
		}
		else {
		    free (texto);
		    return PLACA_ERR_BUFFERLLENO;
		}
	}
	else {
		free(texto);
		return PLACA_ERR_DIRECCIONDISTINTA;
	}
}

int Placa_Enviar(TPlaca* placa, void* mensaje, size_t tam, TDireccion destino) {
	TMensaje t_mensaje;

	if (PLACA_DEBUG) printf("Placa_Enviar:\n mensaje = %s\n tam = %d\n destino = %d\n", (char*)mensaje, tam, destino);

	Mensaje_Crear(&t_mensaje, destino, mensaje);
	Medio_Transmitir(placa->medio, &t_mensaje, tam);
	Mensaje_Destruir(&t_mensaje);
	return PLACA_OK;
}

size_t Placa_Leer(TPlaca* placa, void* destino) {
    if (PLACA_DEBUG) printf("Placa_Leer: placa->buffer_lleno = %d\n", placa->buffer_lleno);
    if (placa->buffer_lleno) {
        strcpy((char*)destino,(char*)placa->mensaje);
        if (PLACA_DEBUG) printf("Placa_Leer: destino = %s\n", destino);
        free(placa->mensaje);
        placa->buffer_lleno = FALSE;
        if (PLACA_DEBUG) printf("Placa_Leer: placa->mensaje = %s\n", placa->mensaje);
        return (size_t)strlen(destino);
    }
    else
        return PLACA_BUFFER_VACIO;
}

int Placa_Conectar(TPlaca* placa, TMedio* medio) {
    int codigo_error;
    placa->medio = medio;
    if (PLACA_DEBUG) printf("Direccion placa: %x\n",placa);
    if (!(codigo_error = Medio_Conectar(placa->medio,placa)))
    	return PLACA_OK;
    else
        return codigo_error;
}

int Placa_Desconectar(TPlaca* placa) {
    if (PLACA_DEBUG) printf("Entra al Placa_Desconectar\n");
	return Medio_Desconectar(placa->medio, placa);
}
